package com.portal.framework.dao;

import java.io.Serializable;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.ArrayUtils;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.dialect.Dialect;
import org.hibernate.impl.SessionImpl;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.portal.framework.common.lang.Caster;
import com.portal.framework.common.lang.ConstructorCaster;
import com.portal.framework.exception.msbuilder.annotation.ExceptionMsg;
import com.portal.framework.exception.AppException;
import com.portal.framework.page.PagerResult;
import com.portal.framework.searchform.SimpleSearchFormSupport;
import com.portal.framework.util.CollectionUtils;
import com.portal.framework.util.DateTimeUtil;
import com.portal.framework.util.HibernateUtil;


/**
 * 抽象的DAO实现类. <br>
 * 泛型C指的是要实现哪个类的DAO.一般为DTO,PK 代表ID的类型<br>
 * 要实现的方法getPersistentClass(). 返回DTO对象的class <BR>
 * <BR>
 * 用法 : <BR>
 * <code>
 *  // 具体每张表的DAO 接口 <BR>
 * public interface XXIDAO extends BaseIDAO&lt;XXDTO, Long&gt;  <BR>
 *   //具体每张表的DAO实现 <BR>
 * public class XXDAO extends BaseHibernateDaoSupport&lt;XXDTO, Long&gt; implements XXIDAO 
 * </code>
 * 
 * @author 卢烁波
 * @date 2007-3-10
 * 
 */
public abstract class BaseHibernateDaoSupport<C, PK extends Serializable>
		extends HibernateDaoSupport implements BaseIDAO<C, PK> {

	public void flushSession() {
		getSession().flush();
	}

	SimpleSearchFormSupport<C> simpleSearchFormSupport;

	void initSearchFormSupport() {
		if (simpleSearchFormSupport == null) {
			simpleSearchFormSupport = new SimpleSearchFormSupport<C>();
			simpleSearchFormSupport
					.setHibernateTemplate(getHibernateTemplate());
			simpleSearchFormSupport.setPersistentClass(getPersistentClass());
		}
	}

	/**
	 * 执行一条HQL语句(DELETE,UPDATE...)
	 * 
	 * @param query
	 *            HQL 语句
	 * @return 返回影响记录数
	 * 
	 */
	public int executeQuery(String query) {
		return this.executeQuery(query, (Object[]) null);
	}

	/**
	 * 通过 SQL 进行删除
	 * 
	 * @param sql
	 * @return
	 * @throws SQLException
	 */
	public int deleteBySQL(String sql) throws SQLException {
		Connection connection = getSession().connection();
		PreparedStatement pStatement = connection.prepareStatement(sql);

		pStatement.execute();
		ResultSet reSet = pStatement.getResultSet();
		if (reSet.next())
			return reSet.getInt(0);
		return 0;
	}

	/**
	 * 得到DAO要实现的哪个类的Class.
	 */
	public abstract Class<C> getPersistentClass();

	/**
	 * 得到ID的名字,对应映射文件中ID字段的名字.
	 * 
	 * @return
	 */
	public String getIDName() {
		return HibernateUtil.getPKFieldName(getSessionFactory(),
				getPersistentClass());
	}

	/**
	 * 根据ID删除一个对象,返回影响的记录数.
	 * 
	 * @param id
	 * @return
	 */
	public int delete(PK id) {
		String str = "DELETE FROM {0} o WHERE o.{1} = ?";
		String delSQL = MessageFormat.format(str, getPersistentClass()
				.getName(), getIDName());

		return this.executeQuery(delSQL, id);
	}

	/**
	 * 根据ID在列表中的所有记录,返回已删除的记录数.
	 * 
	 * @param ids
	 *            ID的数组
	 * 
	 * @return 已删除的记录数
	 * 
	 */
	public int deleteBatch(final PK[] ids) { 
		return this.deleteBatch(ids, null);
	}

	/**
	 * 删除ID在列表中加上where判断语句的所有记录
	 * 
	 * 
	 * @param ids
	 *            要删除的ID数组
	 * @param whereQuery
	 *            where判断语句
	 * @return 已删除的记录数
	 * 
	 */
	public int deleteBatch(final PK[] ids, String whereQuery) {

		if (CollectionUtils.empty(ids)) {
			return 0;
		}

		String str = "DELETE FROM {0}  WHERE {1} IN (:ids)  {2} ";

		if (whereQuery == null) {
			whereQuery = "";
		} else {
			// 如果WHERE语句不是由AND字符串开始的
			if (!whereQuery.trim().toUpperCase().startsWith("AND")) {
				whereQuery = " AND " + whereQuery;
			}
		}

		final String delSQL = MessageFormat.format(str, getPersistentClass()
				.getName(), getIDName(), whereQuery);

		return (Integer) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session.createQuery(delSQL);
						query.setParameterList("ids", ids);
						return query.executeUpdate();
					}
				});
	}

	/**
	 * 批量删除
	 * 
	 * @param delSql
	 *            删除语句
	 * @return
	 */
	public int deleteBatch(final String delSql) {
		return executeQuery(delSql);
	}

	/**
	 * 批量创建
	 */
	public List<C> createBatch(List<C> objs) {
		List<C> lst = new ArrayList<C>();
		if (CollectionUtils.notEmpty(objs)) {
			C o = null;
			for (C obj : objs) {
				o = this.create(obj);
				if (o != null) {
					lst.add(o);
				}
			}
		}
		return lst;
	}

	/**
	 * 批量创建
	 */
	public Set<C> createBatch(Set<C> objs) {
		Set<C> set = new HashSet<C>();
		if (CollectionUtils.notEmpty(objs)) {
			C o = null;
			for (C obj : objs) {
				o = this.create(obj);
				if (o != null) {
					set.add(o);
				}
			}
		}
		return set;
	}

	/**
	 * 批量新增或保存
	 */
	public void saveOrUpdateBatch(Collection<C> objs) {
		if (CollectionUtils.notEmpty(objs)) {
			for (C obj : objs) {
				this.saveOrUpdate(obj);
			}
		}
	}

	/**
	 * 批量更新
	 */
	public List<C> updateBatch(List<C> objs) {
		List<C> lst = new ArrayList<C>();
		if (CollectionUtils.notEmpty(objs)) {
			C o = null;
			for (C obj : objs) {
				o = this.update(obj);
				if (o != null) {
					lst.add(o);
				}
			}
		}
		return lst;
	}

	/**
	 * 传入一个对象,保存或更新该对象
	 * 
	 * @param obj
	 * @return
	 */
	public C saveOrUpdate(C obj) {
		getHibernateTemplate().saveOrUpdate(obj);
		return obj;
	}

	/**
	 * 保存对象
	 * 
	 * @param obj
	 * @return
	 */

	public C create(C obj) {
		getHibernateTemplate().save(obj);
		return obj;
	}

	/**
	 * 更新对象
	 * 
	 * @param obj
	 * @return
	 */
	public C update(C obj) {
		//this.getSession().clear();
		getHibernateTemplate().update(obj);
		return obj;
	}

	/**
	 * 删除传入的对象
	 * 
	 * 
	 * @param obj
	 *            要删除的对象
	 */
	public void delete(C obj) {
		if (obj != null) {
			getHibernateTemplate().delete(obj);
		}
	}

	/**
	 * 批量删除一个List里的全部对象
	 * 
	 * @param objs
	 *            要删除的对象列表
	 */
	public void deleteBatch(List<C> objs) {
		if (CollectionUtils.notEmpty(objs)) {
			getHibernateTemplate().deleteAll(objs);
		}
	}

	/**
	 * 列表所有的对象
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<C> findAll() {
		List lst = getHibernateTemplate().find(
				"FROM " + getPersistentClass().getName() + " o ");
		return (List<C>) lst;
	}

	/**
	 * 根据HQL和参数查找 <code>
	 * 	find("FROM ClassName o WHERE o.name = ? AND o.age = ?","chenxingji" , "11");
	 * </code>
	 * 
	 * @param query
	 * @param os
	 *            HQL中的参数,对应HQL中的问号
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<C> find(String query, Object... os) {
		return this.find(0, query, os);
	}

	/**
	 * 根据HQL和参数查找 <br>
	 * <code>
	 * 	find(100,"FROM ClassName o WHERE o.name = ? AND o.age = ?","chenxingji" , "11");
	 * </code>
	 * 
	 * @param maxResult
	 *            搜索的最大记录
	 * 
	 * @param query
	 *            HQL语句
	 * @param os
	 *            HQL中的参数,对应HQL中的问号
	 * @return
	 */
	public List<C> find(int maxResult, String query, Object... os) {
		return find(maxResult, getPersistentClass(), query, os);
	}

	/**
	 * 根据HQL查找
	 * 
	 * @param query
	 *            HQL语句
	 */
	@SuppressWarnings("unchecked")
	public List<C> find(String query) {
		return this.find(query, (Object[]) null);
	}

	/**
	 * 根据HQL唯一查找,查找到多个对象只返回第一个,如果查找不到返回null
	 * 
	 * @param class
	 *            <T> 要返回的对象的类型
	 * 
	 * @param query
	 * @param os
	 *            SQL语句中的参数
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T> T uniqueFind(Class<T> clazz, String query, Object... os) {
		List lst = null;
		HibernateTemplate ht = getHibernateTemplate();
		ht.setMaxResults(1);
		if (os == null) {
			lst = ht.find(query);
		} else {
			lst = ht.find(query, os);
		}
		ht.setMaxResults(0);
		if (CollectionUtils.empty(lst)) {
			return null;
		}

		return (T) lst.get(0);
	}

	/**
	 * 根据HQL唯一查找,查找到多个对象只返回第一个,如果查找不到返回null
	 * 
	 * @param query
	 * @param os
	 *            SQL语句中的参数
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public C uniqueFind(String query, Object... os) {
		return uniqueFind(getPersistentClass(), query, os);
	}

	/**
	 * 根据HQL唯一查找,查找到多个对象只返回第一个,如果查找不到返回null
	 * 
	 * @param query
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public C uniqueFind(String query) {
		return this.uniqueFind(query, (Object[]) null);
	}

	/**
	 * 执行一条HQL语句(DELETE,UPDATE...)
	 * 
	 * @param query
	 *            HQL语句
	 * @param os
	 * @return 返回影响记录数
	 * 
	 */
	public int executeQuery(String query, Object... os) {
		if (os == null) {
			return getHibernateTemplate().bulkUpdate(query);
		} else {
			return getHibernateTemplate().bulkUpdate(query, os);
		}
	}

	/**
	 * 根据对象的属性和值查找
	 * 
	 * 
	 * @param propName
	 *            属性名
	 * @param value
	 *            属性值
	 * 
	 * @return
	 */
	public List<C> findByProp(String propName, Object value) {
		String hql = "FROM {0} o WHERE o.{1} = ?";
		// 把{0},{1}替换掉

		hql = MessageFormat.format(hql, getPersistentClass().getName(),
				propName);
		return this.find(hql, value);
	}

	/**
	 * 根据ID查找
	 * 
	 * @param pk
	 * @return
	 */
	public C findById(PK pk) {
		Object o = getHibernateTemplate().get(this.getPersistentClass(), pk);
		if (o == null) {
			return null;
		}
		return getPersistentClass().cast(o);
	}

	/**
	 * 根据ID查找
	 * 
	 * @param pk
	 * @return
	 */
	public List<C> findByIds(PK[] pks) {
		if (CollectionUtils.empty(pks)) {
			return new ArrayList<C>();
		}
		String hql = "FROM {0} o WHERE o.{1} IN (:ids)";
		hql = MessageFormat.format(hql, getPersistentClass().getName(),
				getIDName());
		return findByNamedParam(hql, "ids", pks);
	}

	/**
	 * 根据ID查找
	 * 
	 * @param pk
	 *            Id的值
	 * 
	 * @param lockMode
	 *            锁表的级别,参数hibernate文档
	 * @return
	 */
	public C findById(PK pk, LockMode lockMode) {
		Object o = getHibernateTemplate().get(this.getPersistentClass(), pk,
				lockMode);
		if (o == null) {
			return null;
		}
		return getPersistentClass().cast(o);
	}

	/**
	 * 根据ID查找某一个PersistenceObject的对象
	 * 
	 * 
	 * @param pk
	 * @para po 返回的DTO
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T> T findById(Class<T> po, Serializable pk) {
		if (pk == null || po == null) {
			return null;
		}

		T o = (T) getHibernateTemplate().get(po, pk);
		if (o == null) {
			return null;
		}
		return o;
	}

	/**
	 * 传入一条select count(*)的HQL语句,返回记录数
	 * 
	 * 
	 * @param query
	 * @param values
	 *            HQL语句的参数
	 * 
	 * @return 记录数
	 * 
	 */
	public int countQuery(String query, Object... values) {
		Object ret = null;
		if (values == null) {
			ret = getHibernateTemplate().find(query).get(0);
		} else {
			ret = getHibernateTemplate().find(query, values).get(0);
		}
		if (ret instanceof Number) {
			return ((Number) ret).intValue();
		}
		return (Integer) ret;
	}

	/**
	 * 传入一条select count(*)的SQL语句,返回记录数
	 * 
	 * 
	 * @param query
	 * @return 记录数
	 * 
	 */
	public int countQuery(String query) {
		return this.countQuery(query, (Object[]) null);
	}

	/**
	 * 根据字段名,字段值查找不等于传入ID的数据<br>
	 * 一般在更新的时候使用该方法,某一个字段不能重复但不等要更新的ID
	 * 
	 * @param propName
	 *            字段名
	 * 
	 * @param propValue
	 *            字段值
	 * 
	 * @param id
	 *            不等于的ID
	 * @return 对象列表
	 */
	public List<C> findByPropExceptPK(String propName, Object propValue, PK id) {
		String hql = "FROM {0} o WHERE o.{1} = ? AND o.{2} <> ?";
		hql = MessageFormat.format(hql, getPersistentClass().getName(),
				propName, getIDName());

		return this.find(hql, propValue, id);
	}

	/**
	 * 根据HQL和参数查找,参数可以是Collection或数组
	 * 
	 * 
	 * @param query
	 *            HQL语句
	 * @param paramNames
	 *            参数的名字
	 * 
	 * @param values
	 *            值
	 * 
	 * @return 结果列表
	 */
	public List<C> findByNamedParam(String query, String paramName, Object value) {
		return findByNamedParam(getPersistentClass(), query,
				new String[] { paramName }, new Object[] { value });
	}

	/**
	 * 根据HQL和参数查找,参数可以是Collection或数组
	 * 
	 * 
	 * @param cls
	 *            返回值里List的类型
	 * 
	 * @param query
	 *            HQL语句
	 * @param paramNames
	 *            参数的名字
	 * 
	 * @param values
	 *            值
	 * 
	 * @return 结果列表
	 */
	public <T> List<T> findByNamedParam(Class<T> cls, String query,
			String paramName, Object value) {
		return findByNamedParam(cls, query, new String[] { paramName },
				new Object[] { value });
	}

	/**
	 * 根据HQL和参数查找,参数可以是Collection或数组<BR>
	 * 参数个数要与值的个数相等
	 * 
	 * @param query
	 *            HQL语句
	 * @param paramNames
	 *            参数的名字(数组)
	 * @param values
	 *            值(数组)
	 * @return 结果列表
	 */
	public List<C> findByNamedParam(String query, String[] paramNames,
			Object[] values) {
		return this.findByNamedParam(getPersistentClass(), query, paramNames,
				values);
	}

	/**
	 * 根据HQL和参数查找,参数可以是Collection或数组<BR>
	 * 参数个数要与值的个数相等
	 * 
	 * @param cls
	 *            返回值里List的类型
	 * 
	 * @param query
	 *            HQL语句
	 * @param paramNames
	 *            参数的名字(数组)
	 * @param values
	 *            值(数组)
	 * @return 结果列表
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> findByNamedParam(Class<T> cls, String query,
			String[] paramNames, Object[] values) {
		return (List<T>) getHibernateTemplate().findByNamedParam(query,
				paramNames, values);
	}

	/**
	 * �����传入搜索的SearchForm,返回PagerResult(包括对象列表和分页器)
	 * 
	 * @param searchForm
	 *            搜索条件,并包含分页信息
	 * 
	 * @return 结果列表和分页器
	 */
	@SuppressWarnings("unchecked")
	public PagerResult<C> findByCondision(ISearchForm searchForm) {
		return this.findByCondision(searchForm, getPersistentClass());
	}

	/**
	 * �����传入搜索的SearchForm,返回PagerResult(包括对象列表和分页器)
	 * 
	 * @searchClass 搜索的DTO类
	 * 
	 * @param searchForm
	 *            搜索条件,并包含分页信息
	 * 
	 * @param retType
	 *            返回结果的类型
	 * 
	 * @return 结果列表和分页器
	 */
	@SuppressWarnings("unchecked")
	public <T> PagerResult<T> findByCondision(final Class<?> searchClass,
			final ISearchForm searchForm, final Class<T> retType) {
		initSearchFormSupport();
		return simpleSearchFormSupport.findBySearchForm(searchClass,
				searchForm, retType);
	}

	/**
	 * �����传入搜索的SearchForm,返回PagerResult(包括对象列表和分页器)
	 * 
	 * @searchClass 搜索的DTO类
	 * 
	 * @param searchForm
	 *            搜索条件,并包含分页信息
	 * 
	 * @return 结果列表和分页器
	 */
	@SuppressWarnings("unchecked")
	public <T> PagerResult<T> findByCondision(final Class<T> searchClass,
			final ISearchForm searchForm) {
		return findByCondision(searchClass, searchForm, searchClass);

	}

	/**
	 * �����传入搜索的SearchForm,返回PagerResult(包括对象列表和分页器)
	 * 
	 * @param searchForm
	 *            搜索条件,并包含分页信息
	 * 
	 * @param retClass
	 *            返回结果的类型
	 * 
	 * @return 结果列表和分页器
	 */
	@SuppressWarnings("unchecked")
	public <T> PagerResult<T> findByCondision(final ISearchForm searchForm,
			final Class<T> retClass) {
		initSearchFormSupport();
		return simpleSearchFormSupport.findBySearchForm(null, searchForm,
				retClass);
	}

	/**
	 * 执行DELETE 和 UDPATE 的HQL语句
	 * 
	 * @param queryString
	 *            HQL 语句 ,paramNames和values记录数要一样
	 * 
	 * @param paramNames
	 *            传入的参数
	 * 
	 * @param values
	 *            传入的值
	 * 
	 * @return 影响的记录数
	 */
	public int bulkUpdateByNamedParam(final String queryString,
			final String[] paramNames, final Object[] values) {
		if (paramNames.length != values.length) {
			throw new IllegalArgumentException(
					"paramNames and values length must be same!");
		}

		Integer count = (Integer) getHibernateTemplate().execute(
				new HibernateCallback() {
					Object v = null;

					public Object doInHibernate(Session s)
							throws HibernateException {
						Query q = s.createQuery(queryString);
						if (values != null) {
							for (int i = 0; i < values.length; i++) {
								v = values[i];
								if (v instanceof Collection) {
									q.setParameterList(paramNames[i],
											(Collection) v);
								} else if (v instanceof Object[]) {
									q.setParameterList(paramNames[i],
											(Object[]) v);
								} else {
									q.setParameter(paramNames[i], v);
								}
							}
						}
						return new Integer(q.executeUpdate());
					}
				}, true);
		return count.intValue();
	}

	/**
	 * 执行DELETE 和 UDPATE 的HQL语句
	 * 
	 * @param queryString
	 *            HQL 语句
	 * @param paramNames
	 *            传入的参数
	 * 
	 * @param values
	 *            传入的值
	 * 
	 * @return 影响的记录数
	 */
	public int bulkUpdateByNamedParam(final String queryString,
			final String paramNames, final Object values) {
		return this.bulkUpdateByNamedParam(queryString,
				new String[] { paramNames }, new Object[] { values });
	}

	/**
	 * 根据SQL语句进行查找
	 * 
	 * @param sql
	 *            SQL语句
	 * @return 数据的列表
	 * 
	 */
	public List<Object[]> findBySQL(final String sql) {
		return this.findBySQL(sql, (Object[]) null);
	}

	/**
	 * 根据SQL语句进行查找
	 * 
	 * @param sql
	 * @param args
	 *            参数
	 * @return
	 */
	public List<Object[]> findBySQL(final String sql, final Object... args) {
		if (sql == null) {
			return null;
		}

		List list = (List) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						SQLQuery sqlQuery = session.createSQLQuery(sql);
						if (CollectionUtils.notEmpty(args)) {
							for (int i = 0; i < args.length; i++) {
								sqlQuery.setParameter(i, args[i]);
							}
						}
						return sqlQuery.list();
					}
				});

		return list;
	}

	/**
	 * 执行SQL语句
	 * 
	 * @param sql
	 * @param args
	 * @return 影响记录数
	 * 
	 */
	public int executeBySQL(final String sql, final Object... args) {
		if (sql == null) {
			return 0;
		}

		Integer result = (Integer) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						SQLQuery sqlQuery = session.createSQLQuery(sql);
						if (CollectionUtils.notEmpty(args)) {
							for (int i = 0; i < args.length; i++) {
								sqlQuery.setParameter(i, args[i]);
							}
						}
						return sqlQuery.executeUpdate();
					}
				});

		return result;
	}

	/**
	 * 执行SQL语句
	 * 
	 * @param sql
	 *            SQL语句
	 * @return 影响记录数
	 * 
	 */
	public int executeBySQL(final String sql) {
		return this.executeBySQL(sql, (Object[]) null);
	}

	/**
	 * 根据SQL语句进行查找
	 * 
	 * @param cls
	 *            要返回的对象的类型
	 * 
	 * @param sql
	 *            SQL语句
	 * @return 数据的列表
	 * 
	 */
	public <T> List<T> findBySQL(Class<T> cls, String sql) {
		return findBySQL(cls, sql, (Object[]) null);
	}

	/**
	 * 根据SQL语句进行查找
	 * 
	 * @param cls
	 *            要返回的对象的类型
	 * 
	 * @param sql
	 *            SQL语句
	 * @param args
	 *            参数
	 * @return 数据的列表
	 * 
	 */
	public <T> List<T> findBySQL(Class<T> cls, String sql, Object... args) {
		if (cls == null) {
			return null;
		}
		List lst = this.findBySQL(sql, args);
		if (lst == null) {
			return null;
		}
		return CollectionUtils.toList(lst, new ConstructorCaster<T>(cls));
	}

	/**
	 * 根据一条HQL语句进行查询,查询出来的结果一般不是一个DTO对象.
	 * 
	 * @param hql
	 *            HQL语句
	 * @return 对象数组
	 */
	public List<Object[]> findByHQL(String hql) {
		return this.findByHQL(hql, (Object[]) null);
	}

	/**
	 * 根据一条HQL语句进行查询,查询出来的结果一般不是一个DTO对象.
	 * 
	 * @param hql
	 *            HQL语句
	 * @param values
	 *            参数,对应HQL语句中的?
	 * @return 对象数组
	 */
	public List<Object[]> findByHQL(String hql, Object... values) {
		return this.find(Object[].class, hql, values);
	}

	/**
	 * 根据一条HQL语句进行查询,查询出来的结果一般不是一个DTO对象.
	 * 
	 * @param hql
	 *            HQL语句
	 * @return 对象数组
	 */
	@SuppressWarnings("unchecked")
	public Object[] uniqueFindByHQL(String hql) {
		return uniqueFindByHQL(hql, (Object[]) null);
	}

	/**
	 * 根据一条HQL语句进行查询,查询出来的结果一般不是一个DTO对象.
	 * 
	 * @param hql
	 *            HQL语句
	 * @param values
	 *            参数,对应HQL语句中的?
	 * @return 对象数组
	 */
	@SuppressWarnings("unchecked")
	public Object[] uniqueFindByHQL(String hql, Object... values) {
		return uniqueFind(Object[].class, hql, values);
	}

	/**
	 * 创建(增加)的时候判断某一属性是否存在
	 * 
	 * 
	 * @param propName
	 *            属性名
	 * @param propValue
	 *            属性值
	 * 
	 * @return 返回true为存在,否则为不存在
	 */
	public boolean isExistByPropForCreate(String propName, Object propValue) {
		return CollectionUtils.notEmpty(this.findByProp(propName, propValue));
	}

	/**
	 * 更新一时候判断某一属性是否存在(判断时不包括要更新对象的ID)
	 * 
	 * @param propName
	 *            属性名
	 * @param propValue
	 *            属性值
	 * 
	 * @param id
	 *            ID值
	 * 
	 * @return 返回true为存在,否则为不存在
	 */
	public boolean isExistByPropForUpdate(String propName, Object propValue,
			PK id) {
		return CollectionUtils.notEmpty(this.findByPropExceptPK(propName,
				propValue, id));
	}

	/**
	 * 根据HQL和参数查找 <br>
	 * <code>
	 * find(
	 * 		User.class,
	 * 		"SELECT new com.test.User(o.name,o.age) FROM ClassName o WHERE o.name = ? AND o.age = ?",
	 * 		"chenxingji", "11");
	 * </code>
	 * 
	 * @param <T>
	 *            返回列表对象里放的类别
	 * 
	 * @param query
	 *            HQL语句
	 * @param os
	 *            HQL中的参数,对应HQL中的问号
	 * @return 泛型为T的列表
	 * 
	 */
	public <T> List<T> find(Class<T> clazz, String query, Object... os) {
		return this.find(0, clazz, query, os);
	}

	/**
	 * 根据HQL和参数查找 <br>
	 * <code>
	 * find(
	 * 		User.class,
	 * 		"SELECT new com.test.User(o.name,o.age) FROM ClassName o WHERE o.name = ? AND o.age = ?",
	 * 		"chenxingji", "11");
	 * </code>
	 * 
	 * @param <T>
	 *            返回列表对象里放的类别
	 * 
	 * @param query
	 *            HQL语句
	 * @param lockMode
	 *            锁表的类型
	 * 
	 * @param lockAlias
	 * @param os
	 *            HQL中的参数,对应HQL中的问号
	 * @return 泛型为T的列表
	 * 
	 */
	@SuppressWarnings("unchecked")
	public List<C> find(final LockMode lockMode, final String lockAlias,
			final String query, final Object... os) {
		return (List<C>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session s)
							throws HibernateException {

						Query q = s.createQuery(query);
						q.setLockMode(lockAlias, lockMode);

						if (CollectionUtils.notEmpty(os)) {
							for (int i = 0; i < os.length; i++) {
								q.setParameter(i, os[i]);
							}
						}

						return q.list();
					}
				});
	}

	@SuppressWarnings("unchecked")
	public List<C> find(final LockMode lockMode, final String lockAlias,
			final String query) {
		return find(lockMode, lockAlias, query, (Object[]) null);
	}

	/**
	 * 根据HQL和参数查找 <br>
	 * <code>
	 * find(
	 * 		User.class,
	 * 		"SELECT new com.test.User(o.name,o.age) FROM ClassName o WHERE o.name = 'chenxingji' AND o.age = 11");
	 * </code>
	 * 
	 * @param <T>
	 *            返回列表对象里放的类别
	 * 
	 * @param maxResult
	 *            搜索的最大记录
	 * 
	 * @param query
	 *            HQL语句
	 * @return 泛型为T的列表
	 * 
	 */
	public <T> List<T> find(Class<T> clazz, String query) {
		return this.find(clazz, query, (Object[]) null);
	}

	public List<C> find(int firstResult, int maxResult,String query,Object... os) {
		return _find(firstResult,maxResult,getPersistentClass(), query, os);
	}

	/**
	 * 根据HQL和参数查找 <br>
	 * <code>
	 * find(
	 * 		100,
	 * 		User.class,
	 * 		"SELECT new com.test.User(o.name,o.age) FROM ClassName o WHERE o.name = ? AND o.age = ?",
	 * 		"chenxingji", "11");
	 * </code>
	 * 
	 * @param <T>
	 *            返回列表对象里放的类别
	 * 
	 * @param maxResult
	 *            搜索的最大记录
	 * 
	 * @param query
	 *            HQL语句
	 * @param os
	 *            HQL中的参数,对应HQL中的问号
	 * @return 泛型为T的列表
	 * 
	 */
	public <T> List<T> find(int maxResult, Class<T> clazz, String query,
			Object... os) {
		return find(0,maxResult,clazz,query,os);
	}
	/**
	 * 根据HQL和参数查找 <br>
	 * <code>
	 * find(
	 * 		100,
	 * 		User.class,
	 * 		"SELECT new com.test.User(o.name,o.age) FROM ClassName o WHERE o.name = ? AND o.age = ?",
	 * 		"chenxingji", "11");
	 * </code>
	 * 
	 * @param <T>
	 *            返回列表对象里放的类别
	 * 
	 * @param firstResult
	 *            开始的记录
	 * @param maxResult
	 *            搜索的最大记录
	 * 
	 * @param query
	 *            HQL语句
	 * @param os
	 *            HQL中的参数,对应HQL中的问号
	 * @return 泛型为T的列表
	 * 
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> find(int firstResult,int maxResult, Class<T> clazz, String query,
			Object... os) {
		List lst = null;
		if (os == null) {
			lst = _find(firstResult,maxResult,getPersistentClass(),query,(Object[])null);
		} else {
			lst = _find(firstResult,maxResult,getPersistentClass(),query, os);
		}

		if (CollectionUtils.empty(lst)) {
			return Collections.EMPTY_LIST;
		}

		return (List<T>) lst;
	}
	
	<T> List<T> _find(final int firstResult,final int maxResult,Class<T> clazz,final String queryString, final Object[] values) {
		return getHibernateTemplate().executeFind(new HibernateCallback(){
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Query queryObject = session.createQuery(queryString);
				if (firstResult > 0) {
					queryObject.setFirstResult(firstResult);
				}
				if (maxResult > 0) {
					queryObject.setMaxResults(maxResult);
				}
				if (values != null) {
					for (int i = 0; i < values.length; i++) {
						queryObject.setParameter(i, values[i]);
					}
				}
				return queryObject.list();
			}
		});
	}


	/**
	 * 断言某ID记录是否存在,如果不存在就throws AppException
	 * 
	 * @param id
	 *            记录的ID
	 * @throws AppException
	 */
	@ExceptionMsg(code = "app.framework.notexists", msg = "记录不存在")
	public C assertExists(PK id) throws AppException {
		return this.assertExists(id, "app.framework.notexists");
	}

	/**
	 * 断言某ID记录是否存在,如果不存在 throws AppException ,异常的内容为msgCode
	 * 
	 * @param id
	 *            记录的ID
	 * @param msgCode
	 *            异常编码(如:app.modulename.001)
	 * @throws AppException
	 */
	public C assertExists(PK id, String msgCode) throws AppException {
		String hql = "FROM {0} WHERE {1} = ?";
		hql = MessageFormat.format(hql, getPersistentClass().getName(),
				getIDName());
		C ret = this.findById(id);
		if (ret == null) {
			throw new AppException(msgCode);
		}
		return ret;
	}

	/**
	 * 创建新记录的时候,断言一字段是否重复.如果重复 throws AppException ,异常的内容为msgCode
	 * 
	 * @param propName
	 *            属性名
	 * @param propValue
	 *            该属性的值
	 * 
	 * @param msgCode
	 *            异常编码
	 * @throws AppException
	 *             新增时如果记录重复,则throw 该异常
	 * 
	 */ 
	public void assertExistsForCreate(String propName, Object propValue,
			String msgCode) throws AppException {
		if (isExistByPropForCreate(propName, propValue)) {
			throw new AppException(msgCode);
		}

	}

	/**
	 * 更新记录的时候,断言一字段是否重复.如果重复 throws AppException ,异常的内容为msgCode
	 * 
	 * @param propName
	 *            属性名
	 * @param propValue
	 *            该属性的值
	 * 
	 * @param id
	 *            要更新的记录的 ID
	 * @param msgCode
	 *            异常编码
	 * @throws AppException
	 *             更新时如果记录重复,则throw 该异常
	 * 
	 */
	public void assertExistsForUpdate(String propName, Object propValue, PK id,
			String msgCode) throws AppException {
		if (isExistByPropForUpdate(propName, propValue, id)) {
			throw new AppException(msgCode);
		}
	}

	/**
	 * �����传入搜索的SearchForm,返回PagerResult(包括对象列表和分页器) <BR>
	 * 并用构造函数进行构造
	 * 
	 * 
	 * @param searchForm
	 *            搜索条件,并包含分页信息
	 * 
	 * @return 结果列表和分页器
	 */
	@SuppressWarnings("unchecked")
	public <T> PagerResult<T> findByCondisionAndCast(
			final ISearchForm searchForm, final Class<T> clazz) {
		initSearchFormSupport();
		return simpleSearchFormSupport.findBySearchFormAndCast(searchForm,
				clazz);
	}

	@SuppressWarnings("unchecked")
	public <T> PagerResult<T> findByCondisionAndCast(Class<?> searchClazz,
			ISearchForm searchForm, Class<T> retClazz) {
		initSearchFormSupport();
		return simpleSearchFormSupport.findBySearchFormAndCast(searchClazz,
				searchForm, retClazz);
	}

	/**
	 * 创建新记录的时候,断言一字段是否重复.如果重复 throws AppException ,异常的内容为msgCode
	 * 
	 * @param propName[]
	 *            属性名 数组
	 * @param propValue[]
	 *            该属性的值 数组
	 * @param msgCode
	 *            异常编码
	 * @throws AppException
	 *             新增时如果记录重复,则throw 该异常
	 * 
	 */
	public void assertExistsForCreate(String[] propName, Object[] propValue,
			String msgCode) throws AppException {
		if (this.isExistByPropForCreate(propName, propValue)) {
			throw new AppException(msgCode);
		}
	}

	/**
	 * 创建新记录的时候,断言一字段是否重复.如果重复 throws AppException ,异常的内容为msgCode
	 * 
	 * @param propName[]
	 *            属性名 数组
	 * @param propValue[]
	 *            该属性的值 数组
	 * @param msgCode
	 *            异常编码
	 * @throws AppException
	 *             新增时如果记录重复,则throw 该异常
	 * 
	 */
	public void assertExistsForUpdate(String[] propName, Object[] propValue,
			PK id, String msgCode) throws AppException {
		if (this.isExistByPropForUpdate(propName, propValue, id)) {
			throw new AppException(msgCode);
		}
	}

	/**
	 * 创建(增加)的时候判断某一属性是否存在
	 * 
	 * 
	 * @param propName
	 *            属性名数组
	 * @param propValue
	 *            属性值数组
	 * 
	 * @return 返回true为存在,否则为不存在
	 */
	public boolean isExistByPropForCreate(String[] propName, Object[] propValue) {
		String hql = "SELECT COUNT(*) FROM " + getPersistentClass().getName();
		boolean isFirst = true;
		for (String name : propName) {
			if (isFirst) {
				hql += " WHERE " + name + " = ? ";
				isFirst = false;
			} else {
				hql += " AND " + name + " = ?";
			}
		}
		return countQuery(hql, propValue) > 0;
	}

	/**
	 * 更新一时候判断某一属性是否存在(判断时不包括要更新对象的ID)
	 * 
	 * @param propName
	 *            属性名
	 * @param propValue
	 *            属性值
	 * 
	 * @param id
	 *            ID值
	 * 
	 * @return 返回true为存在,否则为不存在
	 */
	public boolean isExistByPropForUpdate(String[] propName,
			Object[] propValue, PK id) {
		String hql = "SELECT COUNT(*) FROM {0} WHERE {1} <> ? ";
		hql = MessageFormat.format(hql, getPersistentClass().getName(),
				getIDName());

		if (propName != null) {
			for (String name : propName) {
				hql += " AND " + name + " = ?";
			}
		}

		Object[] os = ArrayUtils.add(propValue, 0, id);
		return countQuery(hql, os) > 0;
	}

	/**
	 * 根据Store procedure
	 * SQL语句进行查找(只处理有返回值[结果集],最后一个参数为CURSOR,SP参数不可是集合类型,比如Byte[],Int[])
	 * findBySP(Class, "{ call PKG_PERSONAL_LOAN.findReturnMoney(?,?)}",
	 * stateid);
	 * 
	 * @param callsql
	 *            SP SQL语句
	 * @return 数据的列表
	 * 
	 * @author 田才寿
	 * 
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> findBySP(final Class<T> persistentClass,
			final String callsql, final Object... pi) {

		List list = (List) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Connection connection = getSession().connection();
						CallableStatement cstmt = null;
						ResultSet result = null;
						try {
							cstmt = connection.prepareCall(callsql);
							cstmt.clearParameters();
							int poIndex = 1;
							if (pi != null) {
								for (int i = 0; i < pi.length; i++) {
									if (pi[i] == null)
										cstmt.setString(i + 1, null);
									else {
										if (pi[i] instanceof java.util.Date) {
											cstmt
													.setDate(
															i + 1,
															new java.sql.Date(
																	((Date) pi[i])
																			.getTime()));
										} else if (pi[i] instanceof java.sql.Date) {
											cstmt.setDate(i + 1,
													(java.sql.Date) pi[i]);
										} else {
											cstmt.setString(i + 1, pi[i]
													.toString());
										}
									}
								}
								poIndex = pi.length + 1;
							}
							DatabaseType databaseType=getDatabaseType();
							if (databaseType== DatabaseType.DB2_OS400
									|| getDatabaseType() == DatabaseType.DB2) {
								result = cstmt.executeQuery();
								// cstmt.getResultSet();
							} else if(databaseType == DatabaseType.SQLServer||databaseType == DatabaseType.Sybase){
								result = cstmt.executeQuery();
							}else {
//								cstmt.registerOutParameter(poIndex,
//										OracleTypes.CURSOR);
								cstmt.executeUpdate();
								result = (ResultSet) cstmt.getObject(poIndex);
							}

							ResultSetMetaData r = result.getMetaData();
							List<T> list = new ArrayList<T>();
							Caster<T> co = new ConstructorCaster<T>(
									persistentClass);
							while (result.next()) {
								Object[] objs = new Object[r.getColumnCount()];
								for (int i = 0; i < r.getColumnCount(); i++) {
									objs[i] = result.getObject(i + 1);
								}
								list.add(co.cast(objs));
							}
							return list;
						} finally {
							if (result != null)
								result.close();
							if (cstmt != null)
								cstmt.close();
							if (connection != null) {
								connection.close();
							}
						}
					}
				});
		return list;
	}

	/**
	 * 用Store procedure SQL语句来更新DB updateBySP("{ call
	 * PKG_PERSONAL_LOAN.REFRESHLOANSTATUS(?)}", stateid);
	 * 
	 * @param callsql
	 *            SP SQL语句
	 * @author  
	 * 
	 */
	public void updateBySP(final String callsql, final Object... pi) {
		getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				Connection connection = getSession().connection();
				CallableStatement cstmt = null;
				try {
					cstmt = connection.prepareCall(callsql);
					cstmt.clearParameters();
					if (pi != null) {
						for (int i = 0; i < pi.length; i++) {
							if (pi[i] == null)
								cstmt.setString(i + 1, null);
							else {
								if (pi[i] instanceof java.util.Date) {
									cstmt.setDate(i + 1, new java.sql.Date(
											((Date) pi[i]).getTime()));
								} else if (pi[i] instanceof java.sql.Date) {
									cstmt.setDate(i + 1, (java.sql.Date) pi[i]);
								} else {
									cstmt.setString(i + 1, pi[i].toString());
								}
							}
						}
					}
					return cstmt.executeUpdate();
				} finally {
					if (cstmt != null)
						cstmt.close();
					if (connection != null) {
						connection.close();
					}
				}
			}
		});
	}

	/**
	 * 用NamedQuery方法查询数据
	 * SQL语句配置到hbm.xml中,具体实例参考com.htf.gjj.pl.loanbusiness.batchreturn.dto下的
	 * ReturnBillDetailFO.hbm.xml文件 调用List list =
	 * batchReturnDAO.findByNamedQuery("findLoanReturnDetailByReturnBillId",
	 * returnBillId, returnBillId);
	 * 
	 * @params 参数
	 * @author 
	 * 
	 */
	public List findByNamedQuery(String namedQuery, Object... params) {
		List list = getHibernateTemplate().findByNamedQuery(namedQuery, params);
		return list;
	}

	/**
	 * 强制更新Session缓存
	 * 
	 * @params 参数
	 * @author 
	 * 
	 */
	public void refreshSession() {
		getSession().flush();
		getSession().clear();
	}

	/***************************************************************************
	 * 在SQL中,各类型数据库的日期转字符串
	 * 
	 * @param field
	 *            要转换的字段
	 * @param format
	 *            格式
	 * @param len
	 *            转换后的长度
	 * @return
	 */
	public String sqlDateToStr(String field, String format, int len) {
		// String df = DateTimeUtil.formatDate(source, format);
		switch (getDatabaseType()) {
		case Oracle:
			return " TO_CHAR(" + field + ",'" + format + "')";
		case DB2:
		case DB2_OS400:
			return " cast(datefmt(" + field + ",'" + format + "') as char("
					+ len + "))";
			// case ConstSort.DatabaseType_MySQL:
			// case ConstSort.DatabaseType_Sybase:
			// case ConstSort.DatabaseType_SQLServer:
		default:
			return " TO_CHAR(" + field + ",'" + format + "')";
		}
	}

	/***************************************************************************
	 * 在SQL中,各类型数据库的字符串转日期
	 * 
	 * @param field
	 *            要转换的字段
	 * @param format
	 *            格式
	 * @return
	 */
	public String sqlStrToDate(Date source, String format) {
		switch (getDatabaseType()) {
		case Oracle: {
			String df = DateTimeUtil.formatDate(source, format);
			return " TO_DATE('" + df + "','" + format + "')";
		}
		case DB2:
		case DB2_OS400: {
			String df = DateTimeUtil.formatDate(source, "yyyy-MM-dd");
			return " DATE('" + df + "')";
		}
			// case ConstSort.DatabaseType_MySQL:
			// case ConstSort.DatabaseType_Sybase:
			// case ConstSort.DatabaseType_SQLServer:
		default: {
			String df = DateTimeUtil.formatDate(source, format);
			return " TO_DATE('" + df + "','" + format + "')";
		}
		}
	}

	/***************************************************************************
	 * 在SQL中,字段内容为NULL的函数
	 * 
	 * @return
	 */
	public String sqlIsNull() {
		switch (getDatabaseType()) {
		case Oracle: {
			return "NVL";
		}
		case DB2:
		case DB2_OS400: {
			return "VALUE";
		}
			// case ConstSort.DatabaseType_MySQL:
			// case ConstSort.DatabaseType_Sybase:
			// case ConstSort.DatabaseType_SQLServer:
		default: {
			return "NVL";
		}
		}
	}

	/**
	 * 获取当前数据库的类型(DB2 , oracle,mssql....)
	 * 
	 * @return
	 */
	public DatabaseType getDatabaseType() {
		SessionImpl impl = (SessionImpl) getSession();
		Dialect dialect = impl.getFactory().getDialect();
		if (dialect instanceof org.hibernate.dialect.Oracle9Dialect) {
			return DatabaseType.Oracle;
		} else if (dialect instanceof org.hibernate.dialect.DB2400Dialect) {
			return DatabaseType.DB2_OS400;
		} else if (dialect instanceof org.hibernate.dialect.DB2Dialect) {
			return DatabaseType.DB2;
		} else if (dialect instanceof org.hibernate.dialect.MySQLDialect) {
			return DatabaseType.MySQL;
		} else if (dialect instanceof org.hibernate.dialect.SybaseDialect) {
			return DatabaseType.Sybase;
		} else if (dialect instanceof org.hibernate.dialect.SQLServerDialect) {
			return DatabaseType.SQLServer;
		} else {
			return DatabaseType.Oracle;
		}
	}

	public void clearSession() {
		super.getHibernateTemplate().clear();
	}

	/**
	 * 根据一个Map动态更新一个对象
	 * @param entityName 实体的名字,对应hbm.xml class 元素中的 entity-name属性
	 * @param fieldValueMap 属性名和值之间的映射
	 */
	public void dynamicUpdate(final String entityName,
			final Map<String, Object> fieldValueMap) {
		getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				session.getSession(EntityMode.MAP).update(entityName, fieldValueMap);
				return null;
			}
		});
	}
	
	/**
	 * 根据一个Map动态新增一个对象
	 * @param entityName 实体的名字,对应hbm.xml class 元素中的 entity-name属性
	 * @param fieldValueMap 属性名和值之间的映射
	 */
	public Object dynamicSave(final String entityName,
			final Map<String, Object> fieldValueMap) {
		return getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				return session.getSession(EntityMode.MAP).save(entityName, fieldValueMap);
			}
		});
	}
	/**
	 * 格式化sql语句 in 的格式
	 */
	public  String getStringForHQL(Integer[] longIDs) {
		if (longIDs.length == 1) {
			return "  ( '" + longIDs[0] + "' ) ";
		}
		StringBuffer str = new StringBuffer(" ( ");
		for (int i = 0; i < longIDs.length - 1; i++) {
			str.append("'" + longIDs[i] + "',");
		}
		str.append("'" + longIDs[longIDs.length - 1] + "' )");
		return str.toString();
	}
}
